package engine.systems.motion.draggable
{
	import engine.classes.enumerations.Axis;
	import engine.classes.enumerations.SystemPriority;
	import engine.systems.render.render.Render;
	import engine.systems.spatial.spatial.Spatial;
	import engine.systems.update.GameSystem;
	import engine.utils.DisplayUtils;
	import engine.utils.MathUtils;
	
	public class DraggableSystem extends GameSystem
	{
		public function DraggableSystem()
		{
			super(DraggableNode, updateNode, nodeAdded, nodeRemoved);
			
			this.priority = SystemPriority.UPDATE;
		}
		
		private function updateNode(node:DraggableNode, time:Number):void
		{
			var draggable:Draggable = node.draggable;
			var spatial:Spatial 	= node.spatial;
			var render:Render 		= node.render;
			
			if(draggable._invalidate)
			{
				draggable._invalidate = false;
				
				if(draggable._dragging)
				{
					/*
					DisplayObject.mouseX/Y don't account for rotation, so we have to find the
					angle of DisplayObject.mouseX/Y in radians, calculate the radius before the
					rotation, then add the current DisplayObject rotation in radians.
					*/
					var radians:Number 	= Math.atan2(render.display.mouseY, render.display.mouseX);
					var radius:Number 	= render.display.mouseX / Math.cos(radians);
					
					radians += MathUtils.toRadians(render.display.rotation);
					
					draggable._offsetX = Math.cos(radians) * -radius;
					draggable._offsetY = Math.sin(radians) * -radius;
					
					if(draggable.forward) DisplayUtils.toFront(node.render.display);
					
					draggable.drag.dispatch(node.entity);
				}
				else draggable.drop.dispatch(node.entity);
			}
			
			if(draggable._dragging)
			{
				switch(draggable.axis)
				{
					case Axis.X:
						spatial.x = render.display.parent.mouseX + draggable._offsetX;
						break;
					
					case Axis.Y:
						spatial.y = render.display.parent.mouseY + draggable._offsetY;
						break;
					
					case Axis.BOTH:
						spatial.x = render.display.parent.mouseX + draggable._offsetX;
						spatial.y = render.display.parent.mouseY + draggable._offsetY;
						break;
				}
			}
		}
		
		private function nodeAdded(node:DraggableNode):void
		{
			node.interaction.down.add(node.draggable.onDrag);
			node.interaction.up.add(node.draggable.onDrop);
			node.interaction.out.add(node.draggable.onDrop);
		}
		
		private function nodeRemoved(node:DraggableNode):void
		{
			node.interaction.down.remove(node.draggable.onDrag);
			node.interaction.up.remove(node.draggable.onDrop);
			node.interaction.out.remove(node.draggable.onDrop);
		}
	}
}